// Cell names have been changed in this file by netl_namemap on Mon Jan  3 04:00:10 UTC 2022
////////////////////////////////////////////////////////////////////////////// 
//
//  creg_jtag.v
//
//  JTAG CR operation logic.
//
//  Original Author: Chris Jones
//  Current Owner:   Ameer Youssef
//
////////////////////////////////////////////////////////////////////////////// 
//
// Copyright (C) 2013 Synopsys, Inc.  All rights reserved.
//
// SYNOPSYS CONFIDENTIAL - This is an unpublished, proprietary work of
// Synopsys, Inc., and is fully protected under copyright and trade secret
// laws.  You may not view, use, disclose, copy, or distribute this file or
// any information contained herein except pursuant to a valid written
// license agreement. It may not be used, reproduced, or disclosed to others
// except in accordance with the terms and conditions of that agreement.
//
////////////////////////////////////////////////////////////////////////////// 
//
//    Perforce Information
//    $Author: ameer $
//    $File: //dwh/up16/main/dev/pcs_raw/dig/rtl/creg_jtag.v $
//    $DateTime: 2014/11/26 07:44:32 $
//    $Revision: #5 $
//
////////////////////////////////////////////////////////////////////////////// 

`include "dwc_e12mp_phy_x4_ns_jtag_macros.v"
`include "dwc_e12mp_phy_x4_ns_cr_macros.v"   

`timescale 1ns/10fs
module dwc_e12mp_phy_x4_ns_creg_jtag (
   
// JTAG interface
input  wire                        jtag_rst,
input  wire                        jtag_clk,
input  wire                        jtag_clk_n,
input  wire                        jtag_capture,
input  wire                        jtag_shift,
input  wire                        jtag_update,
input  wire                        jtag_ser_in,
input  wire                        jtag_crsel_sel,
output wire                        jtag_crsel_tdo,

// JTAG -> Internal CREG Interface
//output wire                        cr_jtag_clk,
output reg  [`DWC_E12MP_X4NS_CR_ADDR_RANGE]  cr_jtag_addr,
output reg                         cr_jtag_wr_en,
output reg  [`DWC_E12MP_X4NS_CR_DATA_RANGE]  cr_jtag_wr_data,
output reg                         cr_jtag_rd_en,
input  wire [`DWC_E12MP_X4NS_CR_DATA_RANGE]  cr_jtag_rd_data,
input  wire                        cr_jtag_ack
);

reg                                jtag_rd_done;
wire [`DWC_E12MP_X4NS_JTAG_DR_CRSEL_LEN-1:0] jtag_capture_val;
wire [`DWC_E12MP_X4NS_JTAG_DR_CRSEL_LEN-1:0] crsel;
wire [`DWC_E12MP_X4NS_CR_DATA_RANGE]         crsel_data;
wire                               crsel_cmd_read;
wire                               crsel_cmd_write;
wire                               crsel_cmd_addr;

wire                               cr_jtag_rd_en_cmd;
wire                               cr_jtag_wr_en_cmd;

wire                               jtag_update_d;


// When the ack pulses in the jtag clock domain, flag the read operation as complete.
always @(posedge jtag_clk_n or posedge jtag_rst) begin
  if (jtag_rst)
      jtag_rd_done <= 1'd0;
  else if (jtag_update && (cr_jtag_rd_en_cmd || cr_jtag_wr_en_cmd))
      jtag_rd_done <= 1'd0;
  else if (cr_jtag_ack)
      jtag_rd_done <= 1'd1;            
end

// For capture data, put the read data in the lsb's and put the jtag_rd_done bit
// in the MSB so polling software knows when a good value has been written.
assign jtag_capture_val = {jtag_rd_done, 1'b0, cr_jtag_rd_data};

// CRSEL register - accessible via JTAG
// rd_data has multiple tck's to propogate to the register and be sampled... use 2 cycles
// here (works out to 1+delta tck's).  We can bump it up if needed
   //
// %%SYNTH:
//   set_multicycle_path -setup 2 -from $creg_clk -through [get_pins $inst/crsel_reg/capture_val[*]]
//   set_multicycle_path -hold 2 -end -from $creg_clk -through [get_pins $inst/crsel_reg/capture_val[*]]
//
dwc_e12mp_phy_x4_ns_jtag_reg #(.WIDTH(`DWC_E12MP_X4NS_JTAG_DR_CRSEL_LEN),
           .RST_VAL(0))
crsel_reg (
  .q           (crsel),
  .serial_out  (jtag_crsel_tdo),
  .select      (jtag_crsel_sel),
  .capture_val (jtag_capture_val),
  .rst         (jtag_rst),
  .clk         (jtag_clk),
  .capture     (jtag_capture),
  .shift       (jtag_shift),
  .serial_in   (jtag_ser_in)
);
    
// Split crsel register apart into data and command portions
//
assign crsel_data      =  crsel[`DWC_E12MP_X4NS_CR_DATA_RANGE];
assign crsel_cmd_read  = (crsel[`DWC_E12MP_X4NS_CR_DATA_LEN+1:`DWC_E12MP_X4NS_CR_DATA_LEN] == `DWC_E12MP_X4NS_CRSEL_CMD_READ);
assign crsel_cmd_write = (crsel[`DWC_E12MP_X4NS_CR_DATA_LEN+1:`DWC_E12MP_X4NS_CR_DATA_LEN] == `DWC_E12MP_X4NS_CRSEL_CMD_WRITE);
assign crsel_cmd_addr  = (crsel[`DWC_E12MP_X4NS_CR_DATA_LEN+1:`DWC_E12MP_X4NS_CR_DATA_LEN] == `DWC_E12MP_X4NS_CRSEL_CMD_ADDR);

// MOVED TO PCS_RAW_AON_CMN BLOCK
// // CREG clock
// assign cr_jtag_clk = jtag_clk_n;

// Capture address bits for read/write into separate holding register 
// whenever a READ or ADDR command is shifted into the CRSEL register
//
// Note: falling TCK (crsel) -> rising TCK (crsel_addr) path is real
//
always @(posedge jtag_clk_n or posedge jtag_rst) begin
  if (jtag_rst)
    cr_jtag_addr <= {`DWC_E12MP_X4NS_CR_ADDR_LEN{1'b0}};
  else if (jtag_update && jtag_crsel_sel && (crsel_cmd_read || crsel_cmd_addr))
    cr_jtag_addr <= crsel_data;
end

// Capture write data bits for write access into separate holding register 
//
// Note: falling TCK (crsel) -> rising TCK (crsel_addr) path is real
always @(posedge jtag_clk_n or posedge jtag_rst) begin
  if (jtag_rst)
    cr_jtag_wr_data   <= {`DWC_E12MP_X4NS_CR_DATA_LEN{1'b0}};
  else begin
    if (jtag_update && jtag_crsel_sel)
      cr_jtag_wr_data <= crsel_data;
  end
end

// Detect writes to the CRSEL register in order to activate register 
// access sequence.  Note: falling TCK (crsel) -> rising TCK (cr_trig) path
// which is a valid 1/2-cycle path (at low frequency).
//
assign cr_jtag_rd_en_cmd = jtag_crsel_sel && crsel_cmd_read;

assign cr_jtag_wr_en_cmd = jtag_crsel_sel && crsel_cmd_write;


// CR Address decode logic require a cr_clk cycle to generate cr_sel, 
// need to delay the cr_jtag_rd/wr_en signals to the CREGS since a
// requirement for cr_inline_reg is that we cannot assert rd/wr_en
// on the same clock edge as the cr_sel due the pcatch blocks.
// BM_DEBUG: Although I don't see why its necessary!
dwc_e12mp_phy_x4_ns_gen_pipe_dly #(.RST_VAL(0), .PIPE_DLY(1))
jtag_update_pipe (
  .q   (jtag_update_d),
  .clk (jtag_clk_n),
  .rst (jtag_rst),
  .d   (jtag_update)
);

always @(posedge jtag_clk_n or posedge jtag_rst) begin
  if (jtag_rst) begin
    cr_jtag_rd_en <= 1'b0;
    cr_jtag_wr_en <= 1'b0;
  end
  else begin
    cr_jtag_rd_en <= jtag_update_d && cr_jtag_rd_en_cmd;
    cr_jtag_wr_en <= jtag_update_d && cr_jtag_wr_en_cmd;
  end
end

endmodule // creg_jtag
